import json
from django.shortcuts import render
from django.views import View
from meiduo_mall.utils.categories import get_categories
from .models import GoodsCategory,SKU,GoodsVisitCount
from django.core.paginator import Paginator
from . import constants
from django import http
from meiduo_mall.utils.response_code import RETCODE
from meiduo_mall.utils.breadcrumb import get_breadcrumb
from django_redis import get_redis_connection


class ListView(View):
    def get(self,request,category_id,page_num):
        # category_id表示第三及分类的编号.
        # page_num分页
        # 查询分类数据
        categories = get_categories()
        cat3 = GoodsCategory.objects.get(pk=category_id)
        breadcrumb = get_breadcrumb(cat3)
        # 排序规则
        sort=request.GET.get('sort','default')
        if sort == 'default':
            sort_field='-sales'
        elif sort=='price':
            sort_field='price'
        elif sort=='hot':
            sort_field='-comments'
        else:
            sort_field = '-sales'

        # 热销排行（通过ajax请求另一个url暂未实现）！！！！
        # 查询当前页的商品数据
        # 查询指定分类的数据
        skus=SKU.objects.filter(category_id=category_id,is_launched=True).order_by(sort_field)
        # 2.分页
        # 创建分对象，指定列表，页大小
        paginator=Paginator(skus,constants.SKU_LIST_PER_PAGE)
        # 获取指定页码数据
        page_skus=paginator.page(page_num)
        # 获取总页数
        total_page=paginator.num_pages

        context={
            'categories':categories,
            'breadcrumb':breadcrumb,
            'category':cat3,
            'page_skus':page_skus,
            'page_num':page_num,
            'total_page':total_page,
            'sort':sort
        }
        return render(request,'list.html',context)


class HotView(View):
    def get(self,request,category_id):
        # 查询指定分类的热销商品
        cat3 = GoodsCategory.objects.get(pk=category_id)
        skus = cat3.sku_set.order_by('-sales')[0:2]
        sku_list=[]
        for sku in skus:
            sku_list.append({
                'id':sku.id,
                'name':sku.name,
                'price':sku.price,
                'default_image_url':sku.default_image.url
            })

        return http.JsonResponse({
            'code':RETCODE.OK,
            'errmsg':"ok",
            "hot_skus":sku_list
        })


class DetailView(View):
    def get(self, request, sku_id):
        try:
            sku=SKU.objects.get(pk=sku_id)
        except:
            return http.Http404('商品编号无效')
        categories = get_categories()
        # 获取面包屑导航
        breadcrumb=get_breadcrumb(sku.category)
        # 获取spu
        spu =sku.spu
        # 获取规格
        specs=spu.specs.order_by('id')
        # 查询所有的库存商品
        skus=spu.skus.order_by('id')
        # 构造一个规格的空字典备用
        sku_options={}
        sku_option = []
        for sku1 in skus:
            infos=sku1.specs.order_by('spec_id')
            option_key=[]
            for info in infos:
                option_key.append(info.option_id)
                # 获取当前商品的规格信息
                if sku.id == sku1.id:
                    sku_option.append(info.option_id)
            sku_options[tuple(option_key)]=sku1.id

        # 遍历当前spu所有的规格
        spec_list=[]
        for index, spec in enumerate(specs):
            option_list=[]
            for option in spec.options.all():
                # 将当前商品选项进行复制
                sku_option_temp = sku_option[:]
                # 替换对应索引的元素
                sku_option_temp[index] = option.id
                # 为选项添加sku_id属性，用于在html中输出链接
                option.sku_id=sku_options.get(tuple(sku_option_temp), 0)

                # 添加选项对象
                option_list.append(option)
            # 为规格对象添加选项列表
            spec.option_list=option_list

            spec_list.append(spec)
        context={
            'sku':sku,
            'categories':categories,
            'breadcrumb':breadcrumb,
            'category_id':sku.category_id,
            'spu':spu,
            'specs':spec_list
        }

        return render(request,'detail.html',context)


class DetailVisitView(View):
    def post(self,request,category_id):
        try:
            gvc=GoodsVisitCount.objects.get(category_id=category_id)
        except:
            GoodsVisitCount.objects.create(
                category_id=category_id,
                count=1
            )
        else:
            gvc.count+=1
            gvc.save()
        return http.JsonResponse({
            'code':RETCODE.OK,
            'errmsg':'ok'
        })


class HistoryView(View):
    def post(self,request):
        if not request.user.is_authenticated:
            return http.JsonResponse({
                'code': RETCODE.USERERR,
                'errmsg': '未登录，不记录浏览信息',
            })
        dict1=json.loads(request.body.decode())
        sku_id=dict1.get('sku_id')
        if not all([sku_id]):
            return http.JsonResponse({
                'code':RETCODE.PARAMERR,
                'errmsg':'没有商品编号',
            })
        redis_cli=get_redis_connection('history')
        key='history_%d'%request.user.id
        # 删除列表中的元素
        redis_cli.lrem(key,0,sku_id)
        # 加入最前
        redis_cli.lpush(key,sku_id)
        # 截取个数
        redis_cli.ltrim(key,0,4)
        return http.JsonResponse({
            'code':RETCODE.OK,
            'errmsg':'ok'
        })

    def get(self,request):
        if not request.user.is_authenticated:
            return http.JsonResponse({
                'code': RETCODE.USERERR,
                'errmsg': '未登录，不查询浏览信息',
            })

        # 从redis中读取当前用户的对象
        redis_cli=get_redis_connection('history')
        sku_ids_bytes=redis_cli.lrange('history_%d'%request.user.id,0,4)
        # 从redis中取出的数据类型为bytes,需要转化成int类型
        sku_ids_int=[int(sku_id) for sku_id in sku_ids_bytes]
        # 根据商品编号查询商品对象.
        sku_list=[]
        for sku_id in sku_ids_int:
            sku=SKU.objects.get(pk=sku_id)
            sku_list.append({
                'id':sku.id,
                'name':sku.name,
                'price':sku.price,
                'default_image_url':sku.default_image.url
            })
        return http.JsonResponse({
            'code':RETCODE.OK,
            'errmsg':'ok',
            'skus':sku_list
        })